package com.thinkit.cms.config;
import com.thinkit.cms.api.strategy.StrategyService;
import com.thinkit.cms.dto.strategy.StrategyDto;
import com.thinkit.cms.strategy.checker.ActuatorCheck;
import com.thinkit.cms.strategy.filter.Filter;
import com.thinkit.cms.strategy.filter.FilterChain;
import com.thinkit.core.annotation.Actuator;
import com.thinkit.utils.enums.ActionEnum;
import com.thinkit.utils.utils.Checker;
import lombok.extern.slf4j.Slf4j;
import org.reflections.Reflections;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Constructor;
import java.util.Collection;
import java.util.List;
import java.util.Set;

/**
 * @author lg
 * 过滤器链条，可动态实现 执行器的组装拼合
 */
@Slf4j
@Component
public class ActuatorComponent {

    @Autowired
    StrategyService strategyService;


    public void execute(Collection<String> categoryIds, ActionEnum actionEnum, Object params){
        if(Checker.BeNotEmpty(categoryIds)){
            for(String categoryId:categoryIds){
                FilterChain filterChain = chain(categoryId,actionEnum,params);
                if(Checker.BeNotNull(filterChain)){
                    filterChain.doFilter(params,filterChain);
                }
            }
        }
    }

    public void execute(Collection<String> categoryIds, ActionEnum actionEnum, Object params,ActuatorCheck actuatorCheck){
        if(Checker.BeNotEmpty(categoryIds)){
            for(String categoryId:categoryIds){
                FilterChain filterChain = chain(categoryId,actionEnum,params,actuatorCheck);
                if(Checker.BeNotNull(filterChain)){
                    filterChain.doFilter(params,filterChain);
                }
            }
        }
    }

    public void execute(String categoryId,ActionEnum actionEnum,Object params){
        FilterChain filterChain = chain(categoryId,actionEnum,params);
        if(Checker.BeNotNull(filterChain)){
            filterChain.doFilter(params,filterChain);
        }
    }

    public void execute(String categoryId,ActionEnum actionEnum,Object params,ActuatorCheck actuatorCheck){
        FilterChain filterChain = chain(categoryId,actionEnum,params,actuatorCheck);
        if(Checker.BeNotNull(filterChain)){
            actuatorCheck.setAction(actionEnum);
            filterChain.doFilter(params,filterChain);
        }
    }

    private FilterChain chain(String categoryId, ActionEnum actionEnum,Object params,ActuatorCheck actuatorCheck){
        FilterChain filterChain =chain(categoryId,actionEnum,params);
        if(Checker.BeNotNull(filterChain)){
            filterChain.setChecker(actuatorCheck);
        }
        return filterChain;
    }

    private FilterChain chain(String categoryId,ActionEnum actionEnum,Object params){
        String actionCode = actionEnum.getCode();
        List<StrategyDto> actuators= strategyService.queryStrategy(categoryId,actionCode,1);
        log.info("执行器查询结果:"+actuators);
        if(Checker.BeNotEmpty(actuators)){
            FilterChain filterChain = new FilterChain();
            for(StrategyDto actuator:actuators){
                Filter filter = packageFilter(params,actuator,actionEnum);
                log.info("执行器filter:"+filter);
                if(Checker.BeNotNull(filter)){
                    filterChain.addFilter(filter);
                }
            }
            return filterChain.fcount()>0?filterChain:null;
        }
        log.info("=======暂无执行器,请在栏目管理 -> 策略管理 配置执行器==========");
        return null;
    }

    /**
     * 获取执行器
     * @return
     */
    public static Filter packageFilter(String actuatorCode, Object params,StrategyDto strategy,String packageScan,ActionEnum actionEnum){
        Class<?> filterClass = null;
        try {
            Reflections reflections = new Reflections(packageScan);
            Set<Class<?>> clzs = reflections.getTypesAnnotatedWith(Actuator.class);
            log.info("特效子类反射查询结果："+clzs);
            if(Checker.BeNotEmpty(clzs)){
                for(Class<?> clz:clzs ){
                    Actuator actuator = clz.getAnnotation(Actuator.class);
                    if(Checker.BeNotNull(actuator)){
                        String code = actuator.code();
                        if(code.equals(actuatorCode)){
                            filterClass = clz;
                            break;
                        }
                    }
                }
                // 获取 filter 实例
                if(Checker.BeNotNull(filterClass)){
                    Constructor<?> cons = filterClass.getConstructor(Object.class,ActionEnum.class);
                    Filter filter = (Filter)cons.newInstance(params,actionEnum);
                    if(Checker.BeNotNull(strategy)){
                        filter.setStrategy(strategy);
                    }
                    return filter;
                }
            }
        } catch (Exception e) {
            log.error("反射获取异常:"+e.getMessage());
            return null;
        }
        return null;
    }


    public static Filter packageFilter(Object params,StrategyDto actuator,ActionEnum actionEnum){
        String acode = actuator.getActuatorCode();
        return packageFilter(acode,params,actuator,"com.thinkit.cms.strategy.actuator",actionEnum);
    }
}
